package com.chinatechstar.base.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

import com.chinatechstar.admin.entity.SysDict;
import com.chinatechstar.admin.entity.SysUser;
import com.chinatechstar.admin.mapper.SysDictMapper;
import com.chinatechstar.admin.mapper.SysUserMapper;
import com.chinatechstar.base.dto.SysWellTrackDTO;
import com.chinatechstar.base.dto.UploadDailyOilProdDTO;
import com.chinatechstar.base.entity.SysArea;
import com.chinatechstar.base.entity.SysProdOrg;
import com.chinatechstar.base.mapper.SysAreaMapper;
import com.chinatechstar.base.mapper.SysProdOrgMapper;
import com.chinatechstar.component.commons.entity.MapListExcelListenerDTO;
import com.chinatechstar.component.commons.exception.AjaxExceptionEnum;
import com.chinatechstar.component.commons.utils.*;
import com.chinatechstar.file.service.impl.FileServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.chinatechstar.base.entity.SysWell;
import com.chinatechstar.base.mapper.SysWellMapper;
import com.chinatechstar.base.service.SysWellService;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import static java.util.Comparator.comparing;

/**
 * 业务逻辑实现层
 */
@Service
@Transactional
public class SysWellServiceImpl implements SysWellService {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final SequenceGenerator SEQUENCE_GENERATOR = new SequenceGenerator();

    private static final int ITEM_WELL_NAME = 0;
    private static final int ITEM_PROD_DATE = 1;
    private static final int ITEM_OIL_PROD = 2;
    private static final int ITEM_FLUID_PROD = 3;
    private static final int ITEM_WATER_PROD = 4;
    private static final int ITEM_REMARK = 5;

    @Autowired
    private SysWellMapper sysWellMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private FileServiceImpl fileServiceImpl;
    @Autowired
    private SysDictMapper sysDictMapper;
    @Autowired
    private SysProdOrgMapper sysProdOrgMapper;
    @Autowired
    private SysAreaMapper sysAreaMapper;

    /**
     * 查询所有数据
     */
    @Override
    public List<SysWell> findSysWellAll() {
        return sysWellMapper.findSysWellAll();
    }


    /**
     * 查询不分页数据
     */
    @Override
    public List<SysWell> findWellListByCondition(Long wellOrgId, Long wellAreaId, String wellCommonName) {
        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("wellOrgId", wellOrgId);
        paramMap.put("wellAreaId", wellAreaId);
//        paramMap.put("wellCommonName", wellCommonName);

        if (PinyinUtils.isEnglish(wellCommonName)) {
            paramMap.put("pinyin", wellCommonName);
        } else {
            paramMap.put("wellCommonName", wellCommonName);
        }
        return sysWellMapper.findWellListByCondition(paramMap);
    }

    /**
     * 查询井区块不分页数据
     */
    @Override
    public List<SysWell> findWellAreaNameByCondition(String wellAreaName) {
        Map<String, Object> paramMap = new HashMap<>();
        if (PinyinUtils.isEnglish(wellAreaName)) {
            paramMap.put("pinyin", wellAreaName);
        } else {
            paramMap.put("wellAreaName", wellAreaName);
        }
        return sysWellMapper.findWellAreaNameByCondition(paramMap);
    }

    /**
     * 查询分页
     */
    @Override
    public Map<String, Object> findSysWellByCondition(Integer currentPage, Integer pageSize, Long wellOrgId, Long wellAreaId, String wellCommonName, String sorter) {
        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("wellOrgId", wellOrgId);
        paramMap.put("wellAreaId", wellAreaId);
        paramMap.put("wellCommonName", wellCommonName);
        if (StringUtils.isNotBlank(sorter)) {
            String sort = sorter.substring(0, sorter.lastIndexOf('_'));
            String sequence = "ascend".equals(sorter.substring(sorter.lastIndexOf('_') + 1)) ? "ASC" : "DESC";
            paramMap.put("sort", sort);
            paramMap.put("sequence", sequence);
        } else {
            paramMap.put("sort", "createTime");
            paramMap.put("sequence", "DESC");
        }
        Page<Object> page = PageHelper.startPage(currentPage, pageSize);
        List<LinkedHashMap<String, Object>> resultList = sysWellMapper.findSysWellByCondition(paramMap);
        return PaginationBuilder.buildResult(resultList, page.getTotal(), currentPage, pageSize);
    }

    /**
     * 查询导出数据列表
     */
    @Override
    public List<LinkedHashMap<String, Object>> findSysWellForExcel(Map<String, Object> paramMap) {
        return sysWellMapper.findSysWellByCondition(paramMap);
    }

    /**
     * 根据主键ID数据查询数据
     */
    @Override
    public SysWell findSysWellById(Long id) {
        return sysWellMapper.findSysWellById(id);
    }

    /**
     * 根据主键ID数组查询数据
     */
    @Override
    public List<SysWell> findSysWellByIds(Long[] ids) {
        return sysWellMapper.findSysWellByIds(ids);
    }

    /**
     * 根据时间和气体介质查询CO2吞吐效果跟踪数据
     */
    @Override
    public List<LinkedHashMap<String, Object>> findSysWellTrackByDateAndGasMedium(String date, String dict) {
        return sysWellMapper.findSysWellTrackByDateAndGasMedium(date, dict);
    }

    /**
     * 查询所有注气吞吐实施的井
     */
    @Override
    public List<SysWell> findSysWellWithAllImpl() {
        return sysWellMapper.findSysWellWithAllImpl();
    }

    /**
     * 查询目前正在进行注气吞吐实施的井
     */
    @Override
    public List<SysWell> findSysWellWithImpl() {
        return sysWellMapper.findSysWellWithImpl();
    }

    /**
     * 新增
     */
    @Override
    public void insertSysWell(SysWell sysWell) {
        getValidateSysWell(sysWell);

        SysUser currUser = sysUserMapper.getUserByUsername(CurrentUserUtils.getOAuth2AuthenticationInfo().get("name"));

        sysWell.setId(SEQUENCE_GENERATOR.nextId());
        sysWell.setCreateName(currUser.getNickname());
        sysWell.setCreateUsername(currUser.getUsername());
        sysWellMapper.insertSysWell(sysWell);
        logger.info("已新增： {}", sysWell.getId());
    }

    /**
     * 批量新增
     */
    @Override
    public void insertSysWells(List<SysWell> sysWells) {
        List<SysWell> createList = new ArrayList<>();
        SysUser currUser = sysUserMapper.getUserByUsername(CurrentUserUtils.getOAuth2AuthenticationInfo().get("name"));

        for (SysWell sysWell : sysWells) {
            try {
                getValidateSysWell(sysWell);
            } catch (Exception e) {
                continue;
            }

            sysWell.setId(SEQUENCE_GENERATOR.nextId());
            sysWell.setCreateName(currUser.getNickname());
            sysWell.setCreateUsername(currUser.getUsername());
            createList.add(sysWell);
        }

        if (createList.size() > 0) {
            sysWellMapper.insertSysWells(createList);
        }
    }

    /**
     * 编辑
     */
    @Override
    public void updateSysWell(SysWell sysWell) {
        SysWell oldWell = sysWellMapper.findSysWellById(sysWell.getId());
        if (oldWell == null) {
            throw new IllegalArgumentException(AjaxExceptionEnum.WELL_NOT_FIND.getMsg());
        }

        // 验证A2 井ID
        if (!sysWell.getWellId().equals(oldWell.getWellId())) {
            ValidateUtils.validateWellId(sysWell.getWellId());
        }

        // 验证A2 井名称
        if (!sysWell.getWellCommonName().equals(oldWell.getWellCommonName())) {
            ValidateUtils.validateWellName(sysWell.getWellCommonName());
        }

        // 验证区块
        if (!sysWell.getWellAreaId().equals(oldWell.getWellAreaId())) {
            SysArea sysArea = ValidateUtils.validateArea(sysWell.getWellAreaId());
            sysWell.setWellAreaName(sysArea.getAreaName());
        }

        // 验证组织
        if (!sysWell.getWellOrgId().equals(oldWell.getWellOrgId())) {
            SysProdOrg prodOrg = ValidateUtils.validateProdOrg(sysWell.getWellOrgId());
            sysWell.setWellOrgName(prodOrg.getProdOrgName());
        }

        sysWellMapper.updateSysWell(sysWell);
        logger.info("已编辑： {}", sysWell.getId());
    }

    /**
     * 编辑油井产状
     */
    @Override
    public void updateOilProdTrack(SysWellTrackDTO dto) {
        LocalDateTime yesterday = DateUtils.asLocalDateTime(dto.getEffectTime()).minusDays(1);
        // 获取传入日期前一天的数据，计算后赋值到更改的数据上
        Map<Integer, String> currProdMap = new HashMap<>(16);
        currProdMap.put(0, dto.getWellName());
        currProdMap.put(1, DateUtils.localDateTime2Str(DateUtils.asLocalDateTime(dto.getEffectTime()), DateUtils.EXCEL_DAILY_PROD_FORMAT));

    }

    /**
     * 批量编辑
     */
    @Override
    public void updateSysWells(List<SysWell> sysWells) {
        sysWellMapper.updateSysWells(sysWells);
    }

    /**
     * 删除
     */
    @Override
    public void deleteSysWellById(Long id) {
        sysWellMapper.deleteSysWellById(id);
    }

    /**
     * 批量删除
     */
    @Override
    public void deleteSysWellByIds(Long[] ids) {
        sysWellMapper.deleteSysWellByIds(ids);
    }

    /**
     * 软删除
     */
    @Override
    public void softDeleteSysWellById(Long id) {
        SysWell sysWell = sysWellMapper.findSysWellById(id);
        if (sysWell != null) {
            sysWell.setSoftDelete(0);
            sysWellMapper.updateSysWell(sysWell);
        }

    }

    /**
     * 批量软删除
     */
    @Override
    public void softDeleteSysWellByIds(Long[] ids) {
        List<SysWell> sysWells = sysWellMapper.findSysWellByIds(ids);

        if (sysWells.size() > 0) {
            for (SysWell sysWell : sysWells) {
                sysWell.setSoftDelete(0);
            }

            sysWellMapper.updateSysWells(sysWells);
        }
    }

    /**
     * 导入每日油井产状，并计算CO2吞吐效果
     */
    @Override
    public List<String> uploadDailyOilProd(UploadDailyOilProdDTO dto) throws IOException {
        com.chinatechstar.file.entity.File entity = fileServiceImpl.uploadFile(dto.getFile());

        File rootDirectoryPath = new File(ResourceUtils.getURL("classpath:").getPath());
        if (!rootDirectoryPath.exists()) {
            rootDirectoryPath = new File("");
        }
        String path = rootDirectoryPath.getAbsolutePath() + entity.getUrl();

        MapListExcelListenerDTO data = EasyExcelUtils.syncReadByMapListListener(path, 0, 1);
        logger.info("输出数据：{}", data);

        // 判断选择日期与工作表日期是否相同
        LocalDate dtoDate = DateUtils.asLocalDate(dto.getDate());
        LocalDate excelDate = DateUtils.strDate2LocalDate(LocalDate.now().getYear() + "." + data.getSheetName(), DateUtils.EXCEL_TRACK_FORMAT);
        if (!DateUtils.localDateIsEqual(dtoDate, excelDate)) {
            throw new IllegalArgumentException("选择日期与工作表日期不是相同日期，请确认日期相同");
        }

        // 将数据写入到tempMap中，便于查询
        Map<String, Map<Integer, String>> tempMap;
        tempMap = new HashMap<>(16);
        for (Map<Integer, String> item : data.getRows()) {
            tempMap.put(item.get(ITEM_WELL_NAME), item);
        }

        LocalDate rowDate;

        Map<Integer, String> itemMap;

        SysWell sysWell;

        List<String> returnInfo = new ArrayList<>();
        return returnInfo;
    }


    /**
     * 导入CO2吞吐效果追踪表基础数据
     */
    @Override
    public List<String> uploadCo2EffectTrack(MultipartFile file, String dict) throws IOException {
        if (dict == null || "".equals(dict)) {
            throw new IllegalArgumentException("请选择气体介质");
        }

        com.chinatechstar.file.entity.File entity = fileServiceImpl.uploadFile(file);

        File rootDirectoryPath = new File(ResourceUtils.getURL("classpath:").getPath());
        if (!rootDirectoryPath.exists()) {
            rootDirectoryPath = new File("");
        }
        String path = rootDirectoryPath.getAbsolutePath() + entity.getUrl();

        MapListExcelListenerDTO data = EasyExcelUtils.syncReadByMapListListener(path, 0, 4);

        return new ArrayList<>(importCo2EffectTrack(data, dict));
    }

    /**
     * 根据CO2效果追踪Excel数据保存数据
     *
     * @param data Excel数据
     * @param dict 气体介质
     * @return 报错信息
     */
    private List<String> importCo2EffectTrack(MapListExcelListenerDTO data, String dict) {
        String excelDateStr = data.getSheetName();
        if (data.getRows().size() <= 0) {
            throw new IllegalArgumentException("Excel日期：" + excelDateStr + "，表数据为空");
        }

        List<String> returnInfo = new ArrayList<>();
        List<SysDict> sysDictList;
        List<SysProdOrg> insertOrgList = new ArrayList<>();
        List<SysArea> insertAreaList = new ArrayList<>();
        List<SysWell> insertWellList = new ArrayList<>();

        Optional<SysProdOrg> orgOptional;
        Optional<SysArea> areaOptional;
        Optional<SysWell> wellOptional;

        boolean implIsUpdate;
        boolean effectIsUpdate;

        SysDict sysDict = null;
        SysProdOrg sysProdOrg = null;
        SysArea sysArea = null;
        SysWell sysWell = null;
        SysUser sysUser = sysUserMapper.getUserByUsername(CurrentUserUtils.getOAuth2AuthenticationInfo().get("name"));

        Map<String, Object> paramMap;

        String xj = "小计";
        String hj = "合计";
        String zj = "总计";
        String measIncrOil;
        String currPrj;
        String currOrg;
        String currArea = "";
        String currWell;

        Integer displayOrder;
        Integer tempDisplayOrder;

        LocalDateTime localDateTime = LocalDateTime.now();
        String excelDate = localDateTime.getYear() + "." + data.getSheetName();

        for (Map<Integer, String> item : data.getRows()) {

            // 小计清空生产单位，区块
            if (item.get(2) != null && item.get(2).equals(xj)) {
                currArea = "";
                sysProdOrg = null;
                sysArea = null;
                sysWell = null;
                continue;
            }

            // 总计清空项目，单位，区块
            if (item.get(1) != null && item.get(1).equals(hj)) {
                currArea = "";
                sysDict = null;
                sysProdOrg = null;
                sysArea = null;
                sysWell = null;
                continue;
            }

            if (item.get(1) != null && item.get(1).equals(zj)) {
                continue;
            }

            // 处理项目信息，保证项目信息唯一；没有需要管理员添加，不可自动生成
            if (item.get(0) != null && !"".equals(item.get(0))) {
                currPrj = item.get(0);
                sysDictList = sysDictMapper.findSysDictByName(currPrj);

                if (sysDictList.size() == 0) {
                    returnInfo.add("Excel日期：" + excelDateStr + "，缺少项目信息，请联系管理员");
                } else if (sysDictList.size() > 1) {
                    returnInfo.add("Excel日期：" + excelDateStr + "，项目信息重复，请联系管理员");
                } else {
                    sysDict = sysDictList.get(0);
                }
            }

            if (sysDict == null) {
                returnInfo.add("Excel日期：" + excelDateStr + "；井号名称：" + item.get(4) + "，缺少项目信息，请联系管理员");
                continue;
            }

            // 处理生产单位，没有自动生成（数据库与数组同时查询）
            if (item.get(1) != null && !"".equals(item.get(1))) {
                currOrg = item.get(1);
                sysProdOrg = sysProdOrgMapper.findSysProdOrgByName(currOrg);

                if (sysProdOrg == null) {
                    String finalCurrOrg = currOrg;
                    orgOptional = insertOrgList.stream().filter(c -> c.getProdOrgName().equals(finalCurrOrg)).findFirst();

                    if (orgOptional.isPresent()) {
                        sysProdOrg = orgOptional.get();
                    } else {
                        displayOrder = sysProdOrgMapper.findMaxDisplayOrder();
                        if (displayOrder == null) {
                            displayOrder = 1;
                        } else {
                            displayOrder++;
                        }

                        orgOptional = insertOrgList.stream().max(comparing(SysProdOrg::getDisplayOrder));
                        tempDisplayOrder = 0;
                        if (orgOptional.isPresent()) {
                            tempDisplayOrder = orgOptional.get().getDisplayOrder();
                        }

                        sysProdOrg = new SysProdOrg();
                        sysProdOrg.setId(SEQUENCE_GENERATOR.nextId());
                        sysProdOrg.setDisplayOrder(displayOrder > tempDisplayOrder++ ? displayOrder : tempDisplayOrder);
                        sysProdOrg.setProdOrgName(currOrg);
                        sysProdOrg.setCreateName(sysUser.getNickname());
                        sysProdOrg.setCreateUsername(sysUser.getUsername());
                        insertOrgList.add(sysProdOrg);
                    }
                }
            }

            if (sysProdOrg == null) {
                returnInfo.add("Excel日期：" + excelDateStr + "；生产单位名称：" + item.get(1) + "，缺少生产单位信息，请联系管理员");
                continue;
            }

            // 处理区块，区块关联生产单位，没有自动生成（数据库与数组同时查询）
            if (item.get(3) != null && !"".equals(item.get(3))) {
                if (!currArea.equals(item.get(3))) {
                    currArea = item.get(3);
                    sysArea = sysAreaMapper.findSysAreaByAreaNameAndOrgId(item.get(3), sysProdOrg.getId());

                    if (sysArea == null) {
                        Long finalOrgId = sysProdOrg.getId();
                        areaOptional = insertAreaList.stream().filter(c -> c.getAreaName().equals(item.get(3)) && c.getAreaOrgId().equals(finalOrgId)).findFirst();

                        if (areaOptional.isPresent()) {
                            sysArea = areaOptional.get();
                        } else {
                            displayOrder = sysAreaMapper.findMaxDisplayOrderByOrgId(sysProdOrg.getId());
                            if (displayOrder == null) {
                                displayOrder = 1;
                            } else {
                                displayOrder++;
                            }

                            areaOptional = insertAreaList.stream().max(comparing(SysArea::getDisplayOrder));
                            tempDisplayOrder = 0;
                            if (areaOptional.isPresent()) {
                                tempDisplayOrder = areaOptional.get().getDisplayOrder();
                            }

                            sysArea = new SysArea();
                            sysArea.setId(SEQUENCE_GENERATOR.nextId());
                            sysArea.setAreaName(item.get(3));
                            sysArea.setAreaOrgId(sysProdOrg.getId());
                            sysArea.setAreaOrgName(sysProdOrg.getProdOrgName());
                            sysArea.setDisplayOrder(displayOrder > tempDisplayOrder++ ? displayOrder : tempDisplayOrder);
                            sysArea.setCreateName(sysUser.getNickname());
                            sysArea.setCreateUsername(sysUser.getUsername());
                            insertAreaList.add(sysArea);
                        }
                    }
                }
            }

            if (sysArea == null) {
                returnInfo.add("Excel日期：" + excelDateStr + "；区块名称：" + item.get(3) + "，缺少区块信息，请联系管理员");
                continue;
            }

            // 处理井号，没井号自动生成（数据库与数组同时查询）
            if (item.get(4) != null && !"".equals(item.get(4))) {
                currWell = item.get(4);
                sysWell = sysWellMapper.findSysWellByField(sysProdOrg.getId(), sysArea.getId(), currWell);

                if (sysWell == null) {
                    Long finalOrgId = sysProdOrg.getId();
                    Long finalAreaId = sysArea.getId();
                    String finalCurrWell = currWell;
                    wellOptional = insertWellList.stream().filter(c -> c.getWellOrgId().equals(finalOrgId) && c.getWellAreaId().equals(finalAreaId) && c.getWellCommonName().equals(finalCurrWell)).findFirst();

                    if (wellOptional.isPresent()) {
                        sysWell = wellOptional.get();
                    } else {
                        displayOrder = sysWellMapper.findMaxDisplayOrderByOrgIdAndAreaId(sysProdOrg.getId(), sysArea.getId());
                        if (displayOrder == null) {
                            displayOrder = 1;
                        } else {
                            displayOrder++;
                        }

                        wellOptional = insertWellList.stream().max(comparing(SysWell::getDisplayOrder));
                        tempDisplayOrder = 0;
                        if (wellOptional.isPresent()) {
                            tempDisplayOrder = wellOptional.get().getDisplayOrder();
                        }

                        sysWell = new SysWell();
                        sysWell.setId(SEQUENCE_GENERATOR.nextId());
                        sysWell.setWellOrgId(sysProdOrg.getId());
                        sysWell.setWellOrgName(sysProdOrg.getProdOrgName());
                        sysWell.setWellAreaId(sysArea.getId());
                        sysWell.setWellAreaName(sysArea.getAreaName());
                        sysWell.setWellCommonName(item.get(4));
                        sysWell.setDisplayOrder(displayOrder > tempDisplayOrder++ ? displayOrder : tempDisplayOrder);
                        sysWell.setCreateName(sysUser.getNickname());
                        sysWell.setCreateUsername(sysUser.getUsername());
                        insertWellList.add(sysWell);
                    }
                }
            }

            if (sysWell == null) {
                returnInfo.add("Excel日期：" + excelDateStr + "；井号名称：" + item.get(4) + "，缺少井号信息，请联系管理员");
                continue;
            }

            paramMap = new HashMap<>(16);
            paramMap.put("implWellId", sysWell.getId());
            paramMap.put("implTime", excelDate);
            paramMap.put("implRounds", item.get(5));
            paramMap.put("gasMedium", dict);

            implIsUpdate = true;

            paramMap = new HashMap<>(16);
            paramMap.put("effectWellId", sysWell.getId());
            paramMap.put("effectTime", excelDate);
            paramMap.put("displayOrder", item.get(2));
            paramMap.put("gasMedium", dict);
            effectIsUpdate = true;
        }

        if (insertOrgList.size() > 0) {
            sysProdOrgMapper.insertSysProdOrgs(insertOrgList);
        }
        if (insertAreaList.size() > 0) {
            sysAreaMapper.insertSysAreas(insertAreaList);
        }
        if (insertWellList.size() > 0) {
            sysWellMapper.insertSysWells(insertWellList);
        }
        return returnInfo;
    }

    /**
     * 获取验证后的井数据
     */
    private void getValidateSysWell(SysWell sysWell) {
        ValidateUtils.validateWellName(sysWell.getWellCommonName());
        ValidateUtils.validateWellId(sysWell.getWellId());

        SysArea sysArea = ValidateUtils.validateArea(sysWell.getWellAreaId());
        sysWell.setWellAreaName(sysArea.getAreaName());
        SysProdOrg sysProdOrg = ValidateUtils.validateProdOrg(sysWell.getWellOrgId());
        sysWell.setWellOrgName(sysProdOrg.getProdOrgName());
    }
}
